package org.kernely.stream.administration;

import java.util.Collection;

import org.kernely.security.dao.GroupDAO;
import org.kernely.security.dao.UserDAO;
import org.kernely.security.persistence.Group;
import org.kernely.security.persistence.Role;
import org.kernely.security.persistence.User;
import org.kernely.stream.StreamBundle;
import org.kernely.stream.dao.StreamDAO;
import org.kernely.stream.persistence.Stream;
import org.kernely.ui.mvp.KernelyPresenter;
import org.kernely.ui.utils.KernelyNotification;

import com.vaadin.data.Validator.InvalidValueException;
import com.vaadin.ui.Button;
import com.vaadin.ui.Layout;
import com.vaadin.ui.Window;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Window.Notification;

/**
 * The view of the management of the window, containing save and cancel buttons.
 */
public class StreamManagementWindowPresenter extends KernelyPresenter<StreamManagementWindowView> {

	/**
	 * The Stream to edit in edition mode
	 */
	private Stream stream;
	private boolean editMode = false;

	/**
	 * String for the permission to subscribe to, write on and delete a message from a stream.
	 */
	public final static String SUBSCRIPTION_REDACTION_DELETEMESSAGES_RIGHTS_STRING = "subscribe,write,deletemessages";
	/**
	 * String for the permission to subscribe to and write on a stream.
	 */
	public final static String SUBSCRIPTION_REDACTION_RIGHTS_STRING = "subscribe,write";
	/**
	 * String for the permission to subscribe to a stream.
	 */
	public final static String SUBSCRIPTION_RIGHTS_STRING = "subscribe"; 

	/**
	 * The add/edit informations form associated to this window
	 */
	private StreamInformationsView siv;
	private StreamInformationsPresenter sip;

	/**
	 * The add/edit user rights form associated to this window
	 */
	private StreamUserRightsView surv;
	private StreamUserRightsPresenter surp;

	/**
	 * The add/edit user rights form associated to this window
	 */
	private StreamGroupRightsView sgrv;
	private StreamGroupRightsPresenter sgrp;

	/**
	 * Default constructor in creation mode
	 */
	public StreamManagementWindowPresenter(){}

	/**
	 * Constructor for the edition mode
	 * @param ud : the UserDetails to edit
	 */
	public StreamManagementWindowPresenter(Stream s){
		this.stream = s;
		this.editMode = true;
	}


	/**
	 * @see org.kernely.ui.mvp.KernelyPresenter#bind()
	 */
	@Override
	public final void bind() {
		// Add Mode
		if(stream == null){
			sip = new StreamInformationsPresenter();
			surp = new StreamUserRightsPresenter();
			sgrp = new StreamGroupRightsPresenter();
		}
		// edit Mode
		else{
			sip = new StreamInformationsPresenter(stream);
			surp = new StreamUserRightsPresenter(stream);
			sgrp = new StreamGroupRightsPresenter(stream);
		}
		siv = new StreamInformationsView();
		surv = new StreamUserRightsView();
		sgrv = new StreamGroupRightsView();
		sip.setView(siv);
		surp.setView(surv);
		sgrp.setView(sgrv);

		view.getTabsheet().addTab((Layout)sip.getView(), "Informations", null);
		view.getTabsheet().addTab((Layout)surp.getView(), "User rights", null);
		view.getTabsheet().addTab((Layout)sgrp.getView(), "Group rights", null);


		// Add a listener to the save button
		this.view.getSaveButton().addListener(new Button.ClickListener() {
			/**
			 * The Serial Version ID
			 */
			private static final long serialVersionUID = -515612812186312L;

			/**
			 * Action when the button is clicked
			 */
			public void buttonClick(ClickEvent event) {
				if(!StreamBundle.getSecurityService().getCurrentUser().hasOneOf(Role.ROLE_ADMINISTRATOR)){
					view.getWindow().getParent().showNotification("Error", "You are not an administrator !", Notification.TYPE_ERROR_MESSAGE);
				}
				else{
					save();
				}
			}
		});

		// Add a listener to the cancel button
		this.view.getCancelButton().addListener(new Button.ClickListener() {
			/**
			 * The Serial Version ID
			 */
			private static final long serialVersionUID = -515612812186312L;

			/**
			 * Action when the button is clicked
			 */
			public void buttonClick(ClickEvent event) {
				// Close the window
				Window win = (Window)view.getParent();
				win.getParent().removeWindow(win);
			}
		});		
	}

	private void save(){
		try{
			this.siv.getTitle().validate();
			String category = null;
			String streamUid = null;
			Stream newStream = new Stream();
			newStream.setTitle(siv.getTitle().toString());
			
						
			if(!editMode){
				category = Stream.CATEGORY_OTHERS;
				// Create the stream and get its UID.
				streamUid = StreamBundle.getStreamService().createStream(
						siv.getTitle().toString(),
						category);
			} else {
				// Update the stream
				category = stream.getCategory();
				streamUid = stream.getUid();
				newStream.setId(stream.getId());
				newStream.setCategory(stream.getCategory());
				newStream.setUid(stream.getUid());
				newStream.setLocked(stream.getLocked());
				StreamDAO.getInstance().updateStream(newStream);
			}

			// All users which have been removed lose rights on the stream.
			for (User u : this.surp.getRemovedUsers()){
				StreamBundle.getSecurityService().ungrantAuthorization(u,
						category+":"+SUBSCRIPTION_RIGHTS_STRING+":"+streamUid);
				StreamBundle.getSecurityService().ungrantAuthorization(u,
						category+":"+SUBSCRIPTION_REDACTION_RIGHTS_STRING+":"+streamUid);
				StreamBundle.getSecurityService().ungrantAuthorization(u,
						category+":"+SUBSCRIPTION_REDACTION_DELETEMESSAGES_RIGHTS_STRING+":"+streamUid);
			}
			
			// User's permissions
			for(int row : (Collection<Integer>)this.surv.getTable().getItemIds()){
				UserDAO udao = UserDAO.getInstance();
				User user = udao.getUser(row);
				
				// We remove all rights on the stream to the user, to replace with the new rights
				StreamBundle.getSecurityService().ungrantAuthorization(user,
						category+":"+SUBSCRIPTION_RIGHTS_STRING+":"+streamUid);
				StreamBundle.getSecurityService().ungrantAuthorization(user,
						category+":"+SUBSCRIPTION_REDACTION_RIGHTS_STRING+":"+streamUid);
				StreamBundle.getSecurityService().ungrantAuthorization(user,
						category+":"+SUBSCRIPTION_REDACTION_DELETEMESSAGES_RIGHTS_STRING+":"+streamUid);
				
				String newRights;
				int rightsSelected = (Integer)this.surv.getTable().getItem(row).getItemProperty("Rights").getValue();
				if(rightsSelected == StreamUserRightsView.REDACTION_RIGHT){
					newRights = SUBSCRIPTION_REDACTION_RIGHTS_STRING;
				}
				else if (rightsSelected == StreamUserRightsView.DELETE_RIGHT){
					newRights = SUBSCRIPTION_REDACTION_DELETEMESSAGES_RIGHTS_STRING;
				} else {
					newRights = SUBSCRIPTION_RIGHTS_STRING;
				}
				String authorization = category + ":" + newRights + ":" + streamUid;
				StreamBundle.getSecurityService().grantAuthorization(user, authorization);
			}

			// Group's permissions
			
			// All groups which have been removed lose rights on the stream.
			for (Group g : this.sgrp.getRemovedGroups()){
				StreamBundle.getSecurityService().ungrantAuthorization(g,
						category+":"+SUBSCRIPTION_RIGHTS_STRING+":"+streamUid);
				StreamBundle.getSecurityService().ungrantAuthorization(g,
						category+":"+SUBSCRIPTION_REDACTION_RIGHTS_STRING+":"+streamUid);
				StreamBundle.getSecurityService().ungrantAuthorization(g,
						category+":"+SUBSCRIPTION_REDACTION_DELETEMESSAGES_RIGHTS_STRING+":"+streamUid);
			}
			
			
			for(int row : (Collection<Integer>)this.sgrv.getTable().getItemIds()){
				GroupDAO gdao = GroupDAO.getInstance();
				Group g = gdao.getGroupById(row);
				
				// We remove all rights on the stream to the user, to replace with the new rights
				StreamBundle.getSecurityService().ungrantAuthorization(g,
						category+":"+SUBSCRIPTION_RIGHTS_STRING+":"+streamUid);
				StreamBundle.getSecurityService().ungrantAuthorization(g,
						category+":"+SUBSCRIPTION_REDACTION_RIGHTS_STRING+":"+streamUid);
				StreamBundle.getSecurityService().ungrantAuthorization(g,
						category+":"+SUBSCRIPTION_REDACTION_DELETEMESSAGES_RIGHTS_STRING+":"+streamUid);
				
				String rights;
				int rightsSelected = (Integer)this.sgrv.getTable().getItem(row).getItemProperty("Rights").getValue();
				if(rightsSelected == StreamUserRightsView.REDACTION_RIGHT){
					rights = SUBSCRIPTION_REDACTION_RIGHTS_STRING;
				}
				else if (rightsSelected == StreamUserRightsView.DELETE_RIGHT){
					rights = SUBSCRIPTION_REDACTION_DELETEMESSAGES_RIGHTS_STRING;
				}
				else{
					rights = SUBSCRIPTION_RIGHTS_STRING;
				}
				String authorization = category + ":" + rights + ":" + streamUid;
				StreamBundle.getSecurityService().grantAuthorization(g, authorization);
			}

			//Send an event to refresh the background page.
			StreamBundle.getEventBus().broadcastEvent(new ManagementStreamEvent(this));

			// Inform the user
			KernelyNotification notification;
			if (editMode){
				notification = new KernelyNotification("Stream " + newStream.getTitle() + " successfully updated.",KernelyNotification.INFO_ICON);
			}
			else {
				notification = new KernelyNotification("Stream " + newStream.getTitle() + " successfully created.",KernelyNotification.INFO_ICON);
			}
			view.getWindow().getParent().showNotification(notification);

			// Close the window when operation succeeded
			Window win = (Window)view.getParent();
			win.getParent().removeWindow(win);
		}
		catch (InvalidValueException e){
			//Log the failure on screen, to give feedback to the user
			KernelyNotification notification = new KernelyNotification(e.getMessage(),KernelyNotification.ERROR_ICON);
			view.getWindow().showNotification(notification);
		}
	}

}
